#!/usr/bin/python3

# This is a public domain file.

# The code was written by Andrew Cooke (andrew@acooke.org) based on
# a program at http://wiki.bath.ac.uk/display/~ma9mjo/iRiver+s10
# written by Martin Owen which was itself based on a program by
# Laszlo Pandy (http://laszlopandy.com) which I can no longer find.

# Unlike previous versions, this requires Python 3.  The reason for
# this is that byte / unicode handling changed and I have "fixed" the
# code to handle Unicode correctly (so had to choose between Python
# 2 and 3).

# Another change is that the program no longer mangles file paths.


# The program works as a filter - it reads a simple m3u format 
# playlist from stdin (ie a list of file paths) and writes a pla
# format playlist to stdout (or to a file, if one is given on the
# command line).

from sys import argv, stdin, stdout, stderr, exit
from os.path import exists
from struct import pack


def strTo8Bit(text):
  return text.encode('ascii')

def strTo16Bit(text):
  chars = list(text.encode('utf_16')[2:])
  for i in range(0, len(chars), 2):
    chars[i], chars[i+1] = chars[i+1], chars[i]
  return bytes(chars)

def pad(data):
  return data + b'\0' * (512 - len(data))


# The three characters that must come before the file path
PATH_HEADER = b'\0\x1B\0'

# The header at the beginning of the file
FILE_HEADER = strTo8Bit('iriver UMS PLA') \
                + b'\0' * 14 + strTo8Bit('Quick List')


def main():

  # Check number of command line args
  if len(argv) > 2:
    print("Usage:\n ls *.mp3 | m3utopla [output-file]")
    exit(1)

  # Set output from optional command line arg
  if len(argv) == 2:
    dest = argv[1]
    if exists(dest):
      print("Output file {0} already exists".format(dest))
      exit(1)
    out = open(dest, 'bw')
  else:
    out = stdout.buffer

  # Read files from stdin
  tracks = []
  while True:
    track = stdin.readline()
    if not track:
      break
    # Change slash direction
    track = track.strip()
    tracks.append(track.replace('/', '\\'))

  # Write the header
  out.write(pad(pack('>i', len(tracks)) + FILE_HEADER))
  
  # Write out the files
  for track in tracks:
#    print('>' + track + '<', file=stderr)
    offset = track.rfind('\\') + 1
    out.write(pad(pack('>h', offset) + strTo16Bit(track)))
  out.flush()


if __name__ == "__main__":
  main()
